# cython: language_level=3
import asyncio
from collections import defaultdict
import json
import logging
import time
import pandas as pd
from sanic.request import Request
from sanic.views import HTTPMethodView
from app.model_phl.cal_risk_rule import get_newusers_free_rule_main, get_oldusers_free_rule

from utils.decorators import param_check
from utils.response import general_json_res
from .utils import process_phone_number
import app.model_phl.model_main as model_main
import app.model_phl.cal_app_features_v1 as app
import app.model_phl.cal_sms_features_v1 as sms
import app.model_phl.cal_device_features as device
import app.model_phl.cal_app_features_v2 as app_v2
import app.model_phl.cal_device_features_v2 as device_v2
import app.model_phl.cal_contact_features_v2 as contact_v2
import app.model_phl.model_predict as md

from . import serializers
from app.model_phl import utils
from app.model_phl import utils_sql
from app.model_phl import utils_json

import app.model_phl.v4.model_main_v1 as model_main_v4

class Predict(HTTPMethodView):
    """restful接口实例"""

    async def get(self, request, pk=0):
        return general_json_res(404, "no get method.")

    @param_check(
        {
            "Phone",
            "ApplyNO",
        }
    )
    async def post(self, request, pk=0):
        Phone = request.json.get("Phone")
        phone_sub = request.json.get("phone_sub")
        ApplyNO = request.json.get("ApplyNO")
        # 根据手机号和订单号直接拿数据算评分
        free_features = model_main.get_free_features(phone_sub, ApplyNO)
        # obj = await DemoUser.create(name=name)
        return general_json_res(result=free_features)

    # async def post(self, request, pk=0):
    #     Phone = request.json.get("Phone")
    #     ApplyNO = request.json.get("ApplyNO")
    #     print(Phone)
    #     # 处理手机号码
    #     phone_sub = process_phone_number(Phone)
    #     # 根据手机号和订单号直接拿数据算评分
    #     free_features = model_main.get_free_features(phone_sub, ApplyNO)
    #     # obj = await DemoUser.create(name=name)
    #     return general_json_res(result=free_features)


class GetScore(HTTPMethodView):
    async def get(self, request: Request):
        # 接收订单号
        apply_no = request.args.get("ApplyNO")
        # 订单数据
        order_dict = utils_sql.get_mysql_order(apply_no)
        if not order_dict:
            return general_json_res(msg='无效订单')
        # 根据订单获取json文件路径
        json_file_url = utils_sql.get_mysql_json_url(apply_no)
        if not json_file_url:
            return general_json_res(msg='缺少json文件路径')
        # 远程获取JSON数据
        json_string = utils.load_remote_json(json_file_url)
        # 将字符串转成json对象
        json_dict = utils.parse_json(json_string)
        # 读取App数据
        app_string = json_dict.get('apps') if 'apps' in json_dict.keys() else None
        app_df = pd.read_json(app_string) if utils.is_json_string(app_string) else None

        # 联系人 相关参数计算
        con_string = json_dict.get('contacts')
        con_df = pd.read_json(con_string) if utils.is_json_string(con_string) else None

        # 设备信息 相关参数（业务参数）计算
        device_string = json_dict.get('deviceInfo')
        device_dict = utils.parse_json(device_string) if utils.is_json_string(device_string) else None

        # app 相关参数计算
        app_features = await app_v2.cal_app_features(
            app_df=app_df, apply_date=order_dict.get('apply_date')
        )

        # 联系人 相关参数计算
        con_features = await contact_v2.cal_contact_features(contact_df=con_df)
        # 设备信息 相关参数（业务参数）计算
        biz_features = await device_v2.cal_biz_features(
            apply_no=order_dict.get('apply_no'),
            phone=order_dict.get('phone'),
            apply_date=order_dict.get('apply_date'),
            app_id=order_dict.get('app_id'),
            user_id=order_dict.get('user_id'),
            project_id=order_dict.get('project_id'),
            device_dict=device_dict,
            enable=True if request.args.get('CalBizFeatures') == '1' else False
        )
        
        result = {
            **biz_features,
            **app_features,
            **con_features,
        }
        
        # print(result)

        return general_json_res(
            result = result
        )

    async def post(self, request, pk=0):
        Phone = request.json.get("Phone")
        phone_sub = request.json.get("phone_sub")
        ApplyNO = request.json.get("ApplyNO")

        # 指标
        Isrenew = request.json.get("Isrenew")
        age = request.json.get("age")
        Birthday = request.json.get("Birthday")
        in_white_list = request.json.get("in_white_list")
        #如果ApplyDate为空取当前时间
        crawlerDatetime = request.json.get("crawlerDatetime")
        crawlerDatetime = crawlerDatetime if crawlerDatetime else time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        params = request.json
        AppList = request.json.get("AppList")
        SmsList = request.json.get("SmsList")
        DeviceList = request.json.get("deviceInfo")
        contacts = request.json.get("contacts", {})

        # 获得黑名单数据
        BlackList = request.json.get("black_list", {})


        # TODO 这里修改获取方式 业务php传，非业务自己算
        free_features = request.json.get("free_features", {})
        # free_features = {}
        
        # 1 age
        cal_userinfo_features = {
            'age': age,
            'Birthday': Birthday,
            'in_white_list': in_white_list,
        }
        free_features.update(cal_userinfo_features)

        # 添加黑名单模块信息
        free_features.update(BlackList)

        # 协程加速 同时计算app、device和sms
        async def appFunction(AppList):
            AppList = pd.DataFrame(AppList)
            app_features2 = app.calculateFreeAppFeaturesV2(AppList)
            return app_features2
        async def smsFunction(SmsList):
            SmsList = pd.DataFrame(SmsList)
            sms_features = sms.calculate_sms_features(SmsList)
            return sms_features

        async def deviceFunction(DeviceList):
            DeviceList = pd.json_normalize(DeviceList)
            device_features = device.calculateFreeDeviceFeatures(DeviceList)
            return device_features

        async def oldFeatureGet(AppList, contacts):
            # app 相关参数计算
            app_df = pd.DataFrame.from_dict(AppList)
            app_features = await app_v2.cal_app_features(
                app_df=app_df, apply_date=crawlerDatetime
            )
            # 联系人 相关参数计算
            # 如果contacts为空则
            if not contacts:
                con_df = pd.DataFrame()
            else:
                con_df = pd.DataFrame.from_dict(contacts)
            con_features = await contact_v2.cal_contact_features(contact_df=con_df)
            # 整合
            old_features = {
                **app_features,
                **con_features,
            }
            return old_features

        # 并发计算
        async def my_view(free_features, AppList, SmsList, DeviceList, contacts):
            old_features = await oldFeatureGet(AppList, contacts)
            app_features2 = await appFunction(AppList)
            sms_features = await smsFunction(SmsList)
            device_features = await deviceFunction(DeviceList)
            free_features.update(old_features)
            free_features.update(app_features2)
            free_features.update(sms_features)
            free_features.update(device_features)
            return free_features

        free_features = await my_view(free_features, AppList, SmsList, DeviceList, contacts)

        # 4 用户评分模块
        model_score_features = md.get_user_model_score_main(free_features)
        free_features.update(model_score_features)

        # 5 基于指标库和评分模型按着分支驱动决策引擎，进行风控决策
        start = time.time()

        if Isrenew == 0:
            # 新客决策
            ruleResult = get_newusers_free_rule_main(free_features)
        else:
            # 老客决策
            ruleResult = get_oldusers_free_rule(free_features)

        end = time.time()
        running_time = end - start
        print('决策模块耗费时间 : %.5f 秒' % running_time)

        # obj = await DemoUser.create(name=name)

        result = {}
        result['free_features'] = free_features
        result['free_rule'] = ruleResult
        del result['free_rule']['input_params']
        return general_json_res(result=result)



class GetScoreV4(HTTPMethodView):
    async def post(self, request, pk=0):
        Phone = request.json.get("Phone")
        phone_sub = request.json.get("phone_sub")
        ApplyNO = request.json.get("ApplyNO")
        ApplyDate = request.json.get("ApplyNO")

        # 指标
        Isrenew = request.json.get("Isrenew")
        age = request.json.get("age")
        Birthday = request.json.get("Birthday")
        in_white_list = request.json.get("in_white_list")
        #如果ApplyDate为空取当前时间
        crawlerDatetime = request.json.get("crawlerDatetime")
        crawlerDatetime = crawlerDatetime if crawlerDatetime else time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        params = request.json
        AppList = request.json.get("AppList")
        SmsList = request.json.get("SmsList")
        DeviceList = request.json.get("deviceInfo")
        contacts = request.json.get("contacts", {})


        # TODO 这里修改获取方式 业务php传，非业务自己算
        free_features = request.json.get("free_features", {})
        # free_features = {}
        
        # 1 age
        cal_userinfo_features = {
            'age': age,
            'Birthday': Birthday,
            'in_white_list': in_white_list,
            'ApplyNO': ApplyNO,
            'ApplyDate': ApplyDate,
        }
        free_features.update(cal_userinfo_features)

        # 4 用户评分模块
        # model_score_features = md.get_user_model_score_main(free_features)
        model_score_features = model_main_v4.calculate_free_features(free_features,AppList,SmsList)
        print(model_score_features)
        free_features.update(model_score_features)

        # 5 决策暂无
        ruleResult = {}

        # obj = await DemoUser.create(name=name)

        result = {}
        result['free_features'] = free_features
        result['free_rule'] = ruleResult
        
        return general_json_res(result=result)
